package com.itcam.daijia.customer.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSON;
import com.itcam.daijia.common.execption.NGException;
import com.itcam.daijia.common.result.ResultCodeEnum;
import com.itcam.daijia.customer.mapper.CustomerInfoMapper;
import com.itcam.daijia.customer.mapper.CustomerLoginLogMapper;
import com.itcam.daijia.customer.service.CustomerInfoService;
import com.itcam.daijia.model.entity.customer.CustomerInfo;
import com.itcam.daijia.model.entity.customer.CustomerLoginLog;
import com.itcam.daijia.model.form.customer.UpdateWxPhoneForm;
import com.itcam.daijia.model.vo.customer.CustomerLoginVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo> implements CustomerInfoService {

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private CustomerLoginLogMapper customerLoginLogMapper;


    /**
     * 小程序授权登录
     * @param code
     * @return
     */
    @Override
    public Long login(String code) {
        // 定义变量 openId，用于存储获取到的微信用户的 openId
        String openId = null;
        try {
            // 调用微信小程序服务的 getUserService() 方法获取用户服务
            // 然后调用 getSessionInfo(code) 方法，传入 code 参数，获取用户的会话信息
            // 该方法可能会抛出 WxErrorException 异常，需要进行捕获处理
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            // 从会话信息中获取 openId
            openId = sessionInfo.getOpenid();
            // 记录日志，输出获取到的 openId
            log.info("【小程序授权】openid={}", openId);
        } catch (WxErrorException e) {
            // 捕获 WxErrorException 异常，并重新抛出一个运行时异常
            throw new RuntimeException(e);
        }

        // 使用 MyBatis-Plus 的 LambdaQueryWrapper 查询数据库中是否已存在该 openId 的用户记录
        CustomerInfo customerInfo = this.getOne(new LambdaQueryWrapper<CustomerInfo>().eq(CustomerInfo::getWxOpenId, openId));
        // 如果用户不存在
        if (null == customerInfo) {
            // 创建一个新的 CustomerInfo 对象
            customerInfo = new CustomerInfo();
            // 设置用户的昵称，这里使用当前时间戳作为昵称
            customerInfo.setNickname(String.valueOf(System.currentTimeMillis()));
            // 设置用户的头像链接为空字符串
            customerInfo.setAvatarUrl("");
            // 设置用户的微信 openId
            customerInfo.setWxOpenId(openId);
            // 将新用户信息保存到数据库中
            this.save(customerInfo);
        }

        // 创建一个 CustomerLoginLog 对象，用于记录用户登录日志
        CustomerLoginLog customerLoginLog = new CustomerLoginLog();
        // 设置登录日志的用户 ID 为当前用户的 ID
        customerLoginLog.setCustomerId(customerInfo.getId());
        // 设置登录日志的消息为 "小程序登录"
        customerLoginLog.setMsg("小程序登录");
        // 将登录日志插入到数据库中
        customerLoginLogMapper.insert(customerLoginLog);
        // 返回当前用户的 ID
        return customerInfo.getId();
    }

    /**
     * 获取客户登录信息
     *
     * @param customerId 客户ID
     * @return 返回客户登录信息
     */
    @Override
    public CustomerLoginVo getCustomerLoginInfo(Long customerId) {
        // 根据客户ID获取客户信息
        CustomerInfo customerInfo = this.getById(customerId);
        // 创建一个新的CustomerLoginVo对象
        CustomerLoginVo customerLoginVo = new CustomerLoginVo();
        // 将客户信息复制到CustomerLoginVo对象中
        BeanUtils.copyProperties(customerInfo, customerLoginVo);
        // 判断是否绑定手机号码，如果未绑定，小程序发起绑定事件
        boolean isBindPhone = StringUtils.hasText(customerInfo.getPhone());
        // 设置CustomerLoginVo对象的是否绑定手机号码属性
        customerLoginVo.setIsBindPhone(isBindPhone);
        // 返回CustomerLoginVo对象
        return customerLoginVo;
    }

    /**
     * 更新客户微信手机号码
     *
     * @param updateWxPhoneForm 包含客户ID和微信登录凭证的表单
     * @return 返回更新是否成功的布尔值
     */
    @SneakyThrows // 使用SneakyThrows注解来抑制异常忽略方法中的异常，相当于在方法中添加try-catch块来处理异常
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Boolean updateWxPhoneNumber(UpdateWxPhoneForm updateWxPhoneForm) {
        // 通过微信小程序服务获取用户的手机号码信息
        WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(updateWxPhoneForm.getCode());
        // 从获取到的信息中提取手机号码
        String phoneNumber = phoneNoInfo.getPhoneNumber();
        // 记录日志，输出获取到的手机号码信息
        log.info("phoneInfo:{}", JSON.toJSONString(phoneNoInfo));

        // 创建一个新的CustomerInfo对象
        CustomerInfo customerInfo = new CustomerInfo();
        // 设置客户ID
        customerInfo.setId(updateWxPhoneForm.getCustomerId());
        // 设置手机号码
        customerInfo.setPhone(phoneNumber);
        // 更新数据库中的客户信息
        return this.updateById(customerInfo);
    }

    /**
     * 获取客户OpenId
     * @param customerId
     * @return
     */
    @Override
    public String getCustomerOpenId(Long customerId) {
        CustomerInfo customerInfo = this.getOne(new LambdaQueryWrapper<CustomerInfo>()
                .eq(CustomerInfo::getId, customerId)
                .select(CustomerInfo::getWxOpenId));
        return customerInfo.getWxOpenId();
    }


}
